package com.gitee.itembucket.core.theme

import com.germ.germplugin.api.dynamic.gui.*
import com.germ.germplugin.api.event.gui.GermGuiSlotPreClickEvent
import com.gitee.itembucket.ItemBucket
import com.gitee.itembucket.ItemBucket.debug
import com.gitee.itembucket.api.ItemAPI
import com.gitee.itembucket.api.event.BucketEvents
import com.gitee.itembucket.core.bucket.Bucket
import com.gitee.itembucket.core.storage.Storage
import com.gitee.itembucket.util.germ.*
import com.gitee.itembucket.util.germ.germ.GermPartDSL
import org.bukkit.Bukkit
import org.bukkit.OfflinePlayer
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import taboolib.common.platform.function.submitAsync
import taboolib.common5.Coerce
import taboolib.library.configuration.ConfigurationSection
import taboolib.module.configuration.Config
import taboolib.module.configuration.Configuration
import taboolib.platform.util.buildItem
import taboolib.platform.util.giveItem
import taboolib.platform.util.isAir
import taboolib.platform.util.sendLang
import java.text.DecimalFormat
import java.util.*

class GermThemeUI(viewer: Player, player: Player) : ThemeUI(viewer, player) {

    var size = ItemBucket.getSize(viewer)

    var bucket: Bucket? = null

    companion object {

        @Config("germ_ui.yml")
        lateinit var config: Configuration

        val node: ConfigurationSection
            get() = config.getConfigurationSection("item_bucket")!!

        val search
            get() = node.getConfigurationSection("search")!!

        val chestScroll
            get() = node.getConfigurationSection("chest_scroll")!!

        val decimalFormat = DecimalFormat("#.#")

        fun format(amount: Long): String {
            return if (amount > 999) {
                decimalFormat.format((Coerce.toDouble(amount) / 1000.0)) + "k"
            } else amount.toString()
        }

//        @SubscribeEvent
        fun e(e: GermGuiSlotPreClickEvent) {
            val slot = e.germGuiSlot

            // 玩家背包放入仓库
            debug("debug@GermGuiSlotPreClickEvent screen=${e.germGuiScreen.guiName} identity= ${slot.identity} slot=${slot.indexName} type=${e.eventType.name} search=${e.germGuiScreen.isSearch()}")
            if (e.germGuiScreen.guiName == "item_bucket") {
                e.isCancelled = true

                if (slot.identity.contains("germplugin_backpack_") && e.eventType == GermGuiSlot.EventType.SHIFT_LEFT_CLICK) {

                    if (e.germGuiScreen.isSearch()) {
                        e.player.sendLang("search-ban-put")
                        return
                    }

                    val itemStack = slot.itemStack ?: return
                    if (itemStack.isAir()) return
                    addItem(e.player, e.germGuiScreen.getOfflinePlayer(), e.germGuiScreen, itemStack)
                }



            }
        }

//        @SubscribeEvent
//        fun e(e: GermGuiSlotClickEvent) {
//
//        }

        fun GermGuiScreen.isSearch(): Boolean {
            return getBucket() is Bucket.Clone
        }

        // 更新物品堆
        fun updateItem(screen: GermGuiScreen, item: Bucket.Item) {
            val scroll = screen.getGuiPart("chest_scroll") as GermGuiScroll
            val bucket = screen.getBucket()
            val slot = scroll.getGuiPart("item_${bucket.checkItem(item)}", GermGuiSlot::class.java)
            slot?.subscript = format(item.getAmount())
        }

        // 刷新画布
        fun updateItemScreen(screen: GermGuiScreen) {
            val scroll = screen.getGuiPart("chest_scroll") as GermGuiScroll
            val bucket = screen.getBucket()
            scroll.getGuiParts(GermGuiSlot::class.java).forEach {
                if (!it.indexName.startsWith("item_")) return@forEach
                val index = Coerce.toInteger(it.indexName.split("_")[1])
                val item = bucket.getItem(index)
                if (item == null || item.getAmount() == 0L) {
                    it.subscript = null
                    it.itemStack = null
                } else {
                    it.itemStack = item.stack
                    it.subscript = format(item.getAmount())
                }
            }
        }


        // 添加物品堆
        fun addItem(screen: GermGuiScreen, item: Bucket.Item) {
            val bucket = screen.getBucket()
            val index = bucket.addItem(item)
            val scroll = screen.getGuiPart("chest_scroll") as GermGuiScroll
            val slot = scroll.getGuiPart("item_$index", GermGuiSlot::class.java)
            slot?.itemStack = item.stack
            slot?.subscript = format(item.getAmount())
        }

        fun addItem(viewer: Player, player: OfflinePlayer, screen: GermGuiScreen, itemStack: ItemStack) {
            val bucket = screen.getBucket()
            val checkItem = bucket.checkItem(itemStack)
            // 没有在桶内找到物品 放入新的物品
            if (checkItem == -1) {
                val item = Bucket.Item(-1, itemStack.clone(), itemStack.amount.toLong())
                if (BucketEvents.Putup(viewer, player, item).call()) {
                    itemStack.amount = 0
                    addItem(screen, item)
                    submitAsync {
                        Storage.INSTANCE.createItem(player, item).thenAccept {
                            ItemAPI.createPutupItemLog(viewer, player, item.getAmount(), item)
                        }
                    }
                }

            }
            // 找到了物品 叠加物品
            else {
                val item = bucket.getItem(checkItem)!!

                if (BucketEvents.Putup(viewer, player, item).call()) {
                    item.put(itemStack.amount)
                    ItemAPI.createPutupItemLog(viewer, player, itemStack.amount.toLong(), item)
                    itemStack.amount = 0
                    updateItem(screen, item)
                    submitAsync {
                        Storage.INSTANCE.updateItem(player, item)
                    }
                }
            }
        }

        fun GermGuiScreen.getBucket(): Bucket {
            return simpleMap["@Bucket"] as Bucket
        }

        fun GermGuiScreen.getOfflinePlayer(): OfflinePlayer {

            return Bukkit.getOfflinePlayer(simpleMap["@Player"] as UUID)
        }


        fun createScreenBucket(viewer: Player, player: OfflinePlayer, bucket: Bucket): List<GermPartDSL<*>> {

            val size = if (player.isOnline) {
                ItemBucket.getSize(player.player!!)
            } else {
                ItemBucket.getSize(bucket)
            }

            val render = BucketEvents.Render(viewer, player, bucket, size)
            render.call()

            return LayoutBuilder(render.size).map { index, row, column ->
                createTemplate("item0", chestScroll) { slot, _ ->
                    slot as GermSlotDSL
                    slot.enable = true
                    slot.interact = true
                    slot.invalid = false
                    slot.name = "item_$index"
                    slot.identity = "@ItemBucket_$index"
                    slot.locationX =
                        slot.locationX.replace("{row}", row.toString()).replace("{column}", column.toString())
                    slot.locationY =
                        slot.locationY.replace("{row}", row.toString()).replace("{column}", column.toString())

                    val item = bucket.items.getOrNull(index)
                    slot.item = item?.stack
                    slot.subscript = item?.run { format(this.getAmount()) }

                    // 取出一个
                    slot.onclick[GermGuiSlot.EventType.LEFT_CLICK] = {
                        takeoutItem(viewer, player, this, bucket, index, 1)
                    }

                    // 取出十个
                    slot.onclick[GermGuiSlot.EventType.RIGHT_CLICK] = {
                        takeoutItem(viewer, player, this, bucket, index, 10)
                    }

                    // 取出1组
                    slot.onclick[GermGuiSlot.EventType.SHIFT_LEFT_CLICK] = {
                        takeoutItem(viewer, player, this, bucket, index, 64)
                    }


                }
            }
        }

        @Suppress("NAME_SHADOWING")
        private fun takeoutItem(
            viewer: Player,
            player: OfflinePlayer,
            screen: GermGuiScreen,
            bucket: Bucket,
            index: Int,
            amount: Long
        ) {
            modifyItem(player, screen, bucket, index) {
                if (amount == 0L) return@modifyItem
                val amount = get(amount)
                if (amount > 0 && BucketEvents.Takeout(viewer, player, this, amount).call()) {
                    viewer.giveItem(buildItem(this.stack) {
                        this.amount = amount.toInt()
                    })
                    ItemAPI.createTakeoutItemLog(viewer, player, amount, this)
                }
            }
        }

        private fun modifyItem(player: OfflinePlayer, screen: GermGuiScreen, bucket: Bucket, index: Int, block: Bucket.Item.() -> Unit) {
            val item = bucket.getItem(index) ?: return
            block(item)
            if (item.changed) {

                // 如果物品为0 则清除物品
                if (item.getAmount() == 0L) {
                    bucket.items.remove(item)
                    if (screen.isSearch() && player.isOnline) {
                        ItemBucket.getBucket(player).thenAccept {
                            it.items.remove(item)
                        }
                    }
                    updateItemScreen(screen)
                    submitAsync {
                        Storage.INSTANCE.removeItem(player, item)
                    }
                } else {
                    updateItem(screen, item)
                    submitAsync {
                        Storage.INSTANCE.updateItem(player, item)
                    }
                }

            }
        }
    }


    private fun updateUI(screen: GermGuiScreen) {
        val scroll = screen.getGuiPart("chest_scroll") as GermGuiScroll
        scroll.getGuiParts(GermGuiSlot::class.java).forEach {
            if (it.indexName.startsWith("item_")) {
                val index = Coerce.toInteger(it.indexName.split("_")[1])
                val item = bucket?.getItem(index)
                it.itemStack = item?.stack
                it.subscript = item?.run { format(this.getAmount()) }
            }
        }
    }


    override fun open() {
        ItemBucket.getBucket(player).thenAccept { bucket ->
            this.bucket = bucket
            createGUI(viewer) { dsl ->
                dsl.infuse(node)
                dsl.map["@Bucket"] = bucket
                dsl.map["@Player"] = player.uniqueId
                dsl.parts += createDSL<GermInputDSL>(search) {

                    it.onenter = { player, input ->
                        val inputValue = input.input
                        ItemBucket.getBucket(player, inputValue).thenAccept { bucket ->
                            this.bucket = bucket
                            input.germGuiScreen.simpleMap.put("@Bucket",bucket)
                            this.updateUI(input.germGuiScreen)
                        }
                    }

                }

                dsl.parts += createDSL<GermScrollDSL>(chestScroll) { scroll ->
                    scroll.parts += createScreenBucket(viewer, player, bucket)
                }

            }
        }.exceptionally {
            it.printStackTrace()
            null
        }
    }
}